/*
 * TICPY Framework
 * Copyright (C) 2012 Plan Director TICs
 *
----------------------------------------------------------------------------
 * Originally developed by SERPRO
 * Demoiselle Framework
 * Copyright (C) 2010 SERPRO
 *
----------------------------------------------------------------------------
 * This file is part of TICPY Framework.
 *
 * TICPY Framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License version 3
 * along with this program; if not,  see <http://www.gnu.org/licenses/>
 * or write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA  02110-1301, USA.
 *
----------------------------------------------------------------------------
 * Este archivo es parte del Framework TICPY.
 *
 * El TICPY Framework es software libre; Usted puede redistribuirlo y/o
 * modificarlo bajo los términos de la GNU Lesser General Public Licence versión 3
 * de la Free Software Foundation.
 *
 * Este programa es distribuido con la esperanza que sea de utilidad,
 * pero sin NINGUNA GARANTÍA; sin una garantía implícita de ADECUACION a cualquier
 * MERCADO o APLICACION EN PARTICULAR. vea la GNU General Public Licence
 * más detalles.
 *
 * Usted deberá haber recibido una copia de la GNU Lesser General Public Licence versión 3
 * "LICENCA.txt", junto con este programa; en caso que no, acceda a <http://www.gnu.org/licenses/>
 * o escriba a la Free Software Foundation (FSF) Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA.
 */
package py.org.financiero.view;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;

import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.ticpy.tekoporu.annotation.NextView;
import org.ticpy.tekoporu.annotation.PreviousView;
import org.ticpy.tekoporu.stereotype.ViewController;
import org.ticpy.tekoporu.template.AbstractEditPageBean;
import org.ticpy.tekoporu.transaction.Transactional;

import py.org.financiero.business.PermisoBC;
import py.org.financiero.business.UsuarioBC;
import py.org.financiero.business.UsuarioPermisoBC;
import py.org.financiero.domain.Permiso;
import py.org.financiero.domain.Usuario;
import py.org.financiero.domain.UsuarioPermiso;
import py.org.financiero.util.UsuarioUtils;

@ViewController
@PreviousView("/admin/usuarioPermiso_list.xhtml")
@NextView("/admin/usuarioPermiso_edit.xhtml")
public class UsuarioPermisoEditMB extends AbstractEditPageBean<UsuarioPermiso, Integer> {

	private static final long serialVersionUID = 1L;

	@Inject
	private UsuarioPermisoBC usuarioPermisoBC;

	@Inject
	private UsuarioBC usuarioBC;

	@Inject
	private PermisoBC permisoBC;

	@Inject
	UsuarioUtils usuario;
	
	private Usuario usuarioSeleccionado = new Usuario();
	
	private List<Usuario> listaUsuarios;
	
	private List<Usuario> usuariosSeleccionados = new ArrayList<Usuario>();
	private List<Permiso> permisosSeleccionados = new ArrayList<Permiso>();
	
	private List<Permiso> tienePermisos;
	private List<Permiso> noTienePermisos;
	
	private LazyDataModel<Permiso> permisoModel;	

	private HashMap<Usuario, Boolean> usuariosMap = new HashMap<Usuario, Boolean>();
	private HashMap<Integer, Boolean> permisosMap = new HashMap<Integer, Boolean>();
	//Se obtiene el archivo de mensajes
	FacesContext ctx = FacesContext.getCurrentInstance();
	Locale locale = ctx.getViewRoot().getLocale();
	ResourceBundle mensajes = (ResourceBundle) ResourceBundle.getBundle("messages", locale);
	
	/**
	 * Carga la lista de usuario
	 */
	@SuppressWarnings("serial")
	@PostConstruct
	public void loadLazyModel() {
		listaUsuarios = usuarioBC.findAll();
		
		
		permisoModel = new LazyDataModel<Permiso>() {
			
			@Override
			public List<Permiso> load(int first, int pageSize, String sortField,
					SortOrder sortOrder, Map<String, String> filters) {
					
					if(sortField == null) sortField = "id"; //default sort field
					
					List<Permiso> permisoes = new ArrayList<Permiso>();
					permisoes = permisoBC.findPage(pageSize, first, sortField, sortOrder.equals(SortOrder.ASCENDING)? true: false);
					
					//Aplicar filtro sobre el listado
					List<Permiso> filtrados = new ArrayList<Permiso>();
					if(filters != null){
						for(Permiso permiso : permisoes) {
				            boolean match = true;
				 
				            if (filters != null) {
				                for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
				                    try {
				                        String filterProperty = it.next();
				                        Object filterValue = filters.get(filterProperty);
				                        Field field = permiso.getClass().getDeclaredField(filterProperty);
				                        field.setAccessible(true);
				                        String fieldValue = String.valueOf(field.get(permiso));
				                        if(filterValue == null || fieldValue.toLowerCase().contains(filterValue.toString().toLowerCase()))
				                        if(filterValue == null || fieldValue.toLowerCase().contains(filterValue.toString().toLowerCase())) {
				                            match = true;
				                    }
				                    else {
				                            match = false;
				                            break;
				                        }
				                    } catch(Exception e) {
				                        match = false;
				                    }
				                }
				            }
				 
				            if(match) {
				                filtrados.add(permiso);
				            }
				        }
						return filtrados;
					}
					return permisoes;
			}
			
		};
	
		permisoModel.setRowCount(permisoBC.count());
		permisoModel.setPageSize(10);
		
	}
	
	public LazyDataModel<Permiso> getPermisoModel() {
	    return permisoModel;
	}
	
	
	
	/**
	 * Borrado logico
	 */
	@Override
	@Transactional
	public String delete() {
		this.usuarioPermisoBC.delete(getId());
		//this.usuarioPermisoBC.update(getBean());
		FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, mensajes.getString("eliminado.exito"), null);  
        FacesContext.getCurrentInstance().addMessage("suceso", msg); 
		return getPreviousView();
	}

	/**
	 * Inserta un nuevo usuarioPermiso
	 */
	@Override
	@Transactional
	public String insert() {
		//Carga el objeto Usuario a partir del ID obtenido del usuarioConverter
		this.usuarioSeleccionado = usuarioBC.load(this.usuarioSeleccionado.getId());
		
		boolean permisoSeleccionado;
		//Obtiene los objetos Permiso a partir del checkbox y carga en un listado
		for (Iterator<Integer> iter = getPermisosMap().keySet().iterator(); iter.hasNext();) {
			Integer permiso = iter.next();
			permisoSeleccionado = getPermisosMap().get(permiso);
			
			if (permisoSeleccionado) {
				permisosSeleccionados.add(permisoBC.load(permiso));
				iter.remove();
			}
		}
		
		
		UsuarioPermiso usuarioPermiso;
		List<UsuarioPermiso> usuarioPermisos = new ArrayList<UsuarioPermiso>();
		List<Permiso> permisosDelUsuario = new ArrayList<Permiso>();
		
		//Obtiene una lista de los Permisos actuales del usuario seleccionado
		for(UsuarioPermiso usuPermiso: this.usuarioSeleccionado.getUsuarioPermisos()){
			permisosDelUsuario.add(usuPermiso.getPermiso());
		}
		
		//Quita del listado del checkbox los permisos actuales del usuario para solo insertar los nuevos
		for(Permiso permiso: permisosDelUsuario){
			if(permisosSeleccionados.contains(permiso)){
				permisosSeleccionados.remove(permiso);
			}
		}
		
		//Por cada permiso actual verifica si se desmarco del checkbox y lo elimina
		for(Permiso permiso: permisosDelUsuario){
			if(permisosMap.get(permiso.getId()) != null && !permisosMap.get(permiso.getId())){
				for(UsuarioPermiso usuPermiso: permiso.getUsuarioPermisos()){
					if(this.usuarioSeleccionado.equals(usuPermiso.getUsuario())){
						this.usuarioPermisoBC.delete(usuPermiso.getId());
					}
				}
				
			}
		}
		
		//Por cada uno de los permisos seleccionado crea un objeto UsuarioPermiso
		for(Permiso permiso: permisosSeleccionados){
			usuarioPermiso = new UsuarioPermiso();
			usuarioPermiso.setUsuario(this.usuarioSeleccionado);
			usuarioPermiso.setPermiso(permiso);
			usuarioPermisos.add(usuarioPermiso);
		}

		try{
			for(UsuarioPermiso usuPermiso: usuarioPermisos){
				this.usuarioPermisoBC.insert(usuPermiso);
			}
		}catch(javax.persistence.PersistenceException ex){//Si existe el el permiso
			FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, mensajes.getString("usuarioPermiso.existe"), null);  
	        FacesContext.getCurrentInstance().addMessage("suceso", msg);
	        return getNextView();
		}
		
		permisosMap = new HashMap<Integer, Boolean>();
		FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, mensajes.getString("agregado.exito"), null);  
        FacesContext.getCurrentInstance().addMessage("suceso", msg); 
		return getNextView();
	}

	/**
	 * Actualiza un usuarioPermiso
	 */
	@Override
	@Transactional
	public String update() {
		this.usuarioPermisoBC.update(getBean());
		FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, mensajes.getString("modificado.exito"), null);  
        FacesContext.getCurrentInstance().addMessage("suceso", msg); 
		return getPreviousView();
	}

	@Override
	protected void handleLoad() {
		setBean(this.usuarioPermisoBC.load(getId()));
	}

	/**
	 * Actualiza el listado de permisos una vez que se seleccione un usuario
	 */
	public void actualizarPermisos() {
		Usuario usuario = usuarioBC.load(usuarioSeleccionado.getId());
		for (Iterator<Integer> iter = getPermisosMap().keySet().iterator(); iter.hasNext();) {
			iter.next();
			iter.remove();
		}
		Permiso permiso;
		permisosMap = new HashMap<Integer, Boolean>();
		for(UsuarioPermiso usuarioPermiso : usuario.getUsuarioPermisos()){
			permiso = usuarioPermiso.getPermiso();
			permisosMap.put(permiso.getId(), Boolean.TRUE);
		}
		
	}

	public Usuario getUsuarioSeleccionado() {
		return usuarioSeleccionado;
	}

	public void setUsuarioSeleccionado(Usuario usuarioSeleccionado) {
		this.usuarioSeleccionado = usuarioSeleccionado;
	}

	public List<Permiso> getPermisosSeleccionados() {
		return permisosSeleccionados;
	}

	public void setPermisosSeleccionados(List<Permiso> permisosSeleccionados) {
		this.permisosSeleccionados = permisosSeleccionados;
	}


	public List<Usuario> getUsuariosSeleccionados() {
		return usuariosSeleccionados;
	}


	public void setUsuariosSeleccionados(List<Usuario> usuariosSeleccionados) {
		this.usuariosSeleccionados = usuariosSeleccionados;
	}


	public HashMap<Usuario, Boolean> getUsuariosMap() {
		return usuariosMap;
	}


	public void setUsuariosMap(HashMap<Usuario, Boolean> usuariosMap) {
		this.usuariosMap = usuariosMap;
	}


	public HashMap<Integer, Boolean> getPermisosMap() {
		return permisosMap;
	}


	public void setPermisosMap(HashMap<Integer, Boolean> permisosMap) {
		this.permisosMap = permisosMap;
	}


	public List<Usuario> getListaUsuarios() {
		return listaUsuarios;
	}


	public void setListaUsuarios(List<Usuario> listaUsuarios) {
		this.listaUsuarios = listaUsuarios;
	}

	public List<Permiso> getTienePermisos() {
		return tienePermisos;
	}


	public void setTienePermisos(List<Permiso> tienePermisos) {
		this.tienePermisos = tienePermisos;
	}


	public List<Permiso> getNoTienePermisos() {
		return noTienePermisos;
	}


	public void setNoTienePermisos(List<Permiso> noTienePermisos) {
		this.noTienePermisos = noTienePermisos;
	}
	
}
